//
//  RunLoop.cpp
//  Simulation
//
//  Created by Christopher Kemsley on 2/24/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "RunLoop.hpp"
#include "Log.hpp"


using namespace Sim ;




/***** RunLoop *****/

// Getting the current run loop
RunLoop&	RunLoop :: currentLoop ()
	{
	static RunLoop l ;
	return l ;
	}

RunLoop :: RunLoop ()
:	SystemController()
,	mSources()
,	mPool()
	{
	
	}
RunLoop :: ~RunLoop ()
	{
	
	}
Interval const	RunLoop :: minimumTimeInterval () const
	{
	Interval	nearest	=	Interval::distantFuture ;
	Log::states("RunLoop") << "Starting minimumInterval search at " << nearest ;
	
	Sources::const_iterator	here	=	mSources.begin() ;
	Sources::const_iterator	end		=	mSources.end() ;
	while ( here != end )
		{
		RunLoopSource * source = *(here++) ;
		Interval	date	=	source->fireDate() ;
		if ( date < nearest )
			{
			Log::states("RunLoop") << "Found nearer at " << date ;
			nearest = date ;
			}
		}
	
	if ( nearest == Interval::distantFuture )
		return Interval::distantFuture ;
	return nearest - System::shared().currentTime() ;
	}

AutoreleasePool&	RunLoop :: currentPool ()
	{
	return mPool ;
	}


// Running the loop
void	RunLoop :: run	()
	{
	Sources sources = mSources ;
	Sources::iterator	here	=	sources.begin() ;
	Sources::iterator	end		=	sources.end() ;
	while ( here != end )
		{
		RunLoopSource * source = *(here++) ;
		if ( mSources.find(source) != mSources.end() )
			{
			Log::states("RunLoop") << "Running source " << source ;
			source -> fire () ;
			}
		}
	mPool . drain() ;
	}





void	RunLoopSource :: performRegistration ()
	{
	Log::states("RunLoop") << "Adding source " << this ;
	RunLoop::currentLoop() . mSources . insert ( this ) ;
	}
void	RunLoopSource :: performUnregistration ()
	{
	Log::states("RunLoop") << "Removing source " << this ;
	RunLoop::currentLoop() . mSources . erase ( this ) ;
	}


Interval const	RunLoopSource :: fireDate ()
	{
	return Interval::distantFuture ;
	}
